import pyglet
import sys,os
import glob
from pyglet.gl import *
from pyglet.window import key,mouse

from framework import *
from widget import *


class ZoomViewControl(icuControl):

    def on_key_press(self, symbol, modifiers):
        if symbol == key.LEFT:
            self.mode.prevPic()
        elif symbol == key.RIGHT:
            self.mode.nextPic()
        elif symbol == key.UP:
            self.mode.dirUp()
        elif symbol == key.DOWN:
            self.mode.chooseDir()
        elif symbol == key.Z and (modifiers & key.MOD_CTRL):
            self.mode.zoom(self.mode.cur_scale * 2.0)
        elif symbol == key.O and (modifiers & key.MOD_CTRL):
            self.mode.zoom(self.mode.cur_scale * 0.5)
        return False

    def on_mouse_press(self,x,y,button,modifiers):
        if button == mouse.RIGHT:
            self.mode.openPieMenu(x,y)

    def on_mouse_drag(self,x,y,dx,dy,button,modifiers):
        if button == mouse.LEFT:
            self.mode.pan(dx,dy)

    def on_resize(self, width, height):
        self.mode.recalcpos(width, height)
        return False


class ZoomViewView(icuView):
    def __init__(self, mode):
        self.closinganim = False
        self.mode = mode
        self.image = None

    def update(self, dt): pass

    def draw(self):
        self.image.draw()


class ZoomViewMode(icuMode):
    
    def __init__(self):
        self.control = ZoomViewControl(self)
        self.view = ZoomViewView(self)
        if len(main.piclist) == 0:
            self.view.image = pyglet.sprite.Sprite(pyglet.image.load("ChangedImage.png"))
        else:
            self.view.image = pyglet.sprite.Sprite(main.cache[main.curCacheIndex])
        self.cur_scale = 1.0 # This is provisional for now, maybe we'll need it later

    def upperlayer(self): return False

    def nextPic(self):
        if len(main.piclist) > 0:
            main.curIndex = (main.curIndex + 1) % len(main.piclist)
            if len(main.piclist) > 3:
                # Have to shift the cache to the left
                main.cache[0] = main.cache[1]
                main.cache[1] = main.cache[2]
                main.cache[2] = None
#                main.cache[2] = pyglet.image.load(main.piclist[(main.curIndex+1) % len(main.piclist)])
                self.view.image = pyglet.sprite.Sprite(main.cache[1])
            else:
                # Small directory, don't need to adjust cache contents at all
                # Just change the cache index
                main.curCacheIndex = main.curCacheIndex+1 % len(main.cache)
                self.view.image = pyglet.sprite.Sprite(main.cache[main.curCacheIndex])
                self.cur_scale = 1.0
    
    def prevPic(self):
        if len(main.piclist) > 0:
            main.curIndex = (main.curIndex - 1) % len(main.piclist)
            if len(main.piclist) > 3:
                # Have to shift the cache to the right
                main.cache[2] = main.cache[1]
                main.cache[1] = main.cache[0]
                main.cache[0] = None
#                main.cache[0] = pyglet.image.load(main.piclist[(main.curIndex-1) % len(main.piclist)])
                self.view.image = pyglet.sprite.Sprite(main.cache[1])
            else:
                # Small directory, don't need to adjust cache contents at all
                # Just change the cache index
                main.curCacheIndex = main.curCacheIndex-1 % len(main.cache)
                self.view.image = pyglet.sprite.Sprite(main.cache[main.curCacheIndex])
                self.cur_scale = 1.0
    
    def dirUp(self):
        main.loadDir(os.path.dirname(main.curdir))
        if len(main.piclist) == 0:
            self.view.image = pyglet.sprite.Sprite(pyglet.image.load("ChangedImage.png"))
        else:
            self.view.image = pyglet.sprite.Sprite(main.cache[main.curCacheIndex])

    def chooseDir(self):
        option = main.findFile()
        main.winman.window.activate()
        if option:
            main.loadDir(option)
            if len(main.piclist) == 0:
                self.view.image = pyglet.sprite.Sprite(pyglet.image.load("ChangedImage.png"))
            else:
                self.view.image = pyglet.sprite.Sprite(main.cache[main.curCacheIndex])

    def pan(self,dx,dy):
        w, h = main.winman.window.get_size()
        if self.view.image.width < w:
            if self.view.image.x + dx > 0 and self.view.image.x + self.view.image.width + dx < w:
                self.view.image.x += dx
        else:
            if self.view.image.x + dx <= 0 and (self.view.image.x + dx) > w-self.view.image.width:
                self.view.image.x += dx
                
        if self.view.image.height < h:
            if self.view.image.y + dy > 0 and self.view.image.y + self.view.image.height + dy < h:
                self.view.image.y += dy
        else:
            if self.view.image.y + dy <= 0 and self.view.image.y + dy > h-self.view.image.height:
                self.view.image.y += dy
        #print self.view.image.x, self.view.image.y

    def recalcpos(self, new_width, new_height):
        if new_width > self.view.image.width:
            self.view.image.x = (new_width // 2) - (self.view.image.width // 2)
        elif new_width < self.view.image.width:
            self.view.image.x = (new_width - self.view.image.width) // 2
        if new_height > self.view.image.height:
            self.view.image.y = (new_height // 2) - (self.view.image.height // 2)
        elif new_height < self.view.image.height:
            self.view.image.y = (new_height - self.view.image.height) // 2
        
    def zoom(self, new_scale):
        w, h = main.winman.window.get_size()
        self.view.image.scale = new_scale
        self.view.image.x = max((min(self.view.image.x * new_scale, 0), w))
        self.view.image.y = max((min(self.view.image.y * new_scale, 0), h))
        if self.view.image.x + self.view.image.width > w: self.view.image.x = w - self.view.image.width
        if self.view.image.y + self.view.image.height > h: self.view.image.y = h - self.view.image.height
        #print self.view.image.x, self.view.image.y
        self.cur_scale = new_scale
        self.recalcpos(w, h)

    def draw(self):
        self.view.draw()
        if main.cache[2] is None:
            main.cache[2] = pyglet.image.load(main.piclist[(main.curIndex+1) % len(main.piclist)])
        elif main.cache[0] is None:
            main.cache[0] = pyglet.image.load(main.piclist[(main.curIndex-1) % len(main.piclist)])
        

    def openPieMenu(self,x,y): pass # Want to get zoom functionality correct first before I worry about this


class PixelZoomViewView(icuView):
    
    def __init__(self, mode):
        self.closinganim = False
        self.mode = mode
        self.image = None

    def update(self, dt): pass

    def draw(self):
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
        self.image.draw()
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)


class PixelZoomViewMode(ZoomViewMode):
    
    def __init__(self):
        self.control = ZoomViewControl(self)
        self.view = PixelZoomViewView(self)
        if len(main.piclist) == 0:
            self.view.image = pyglet.sprite.Sprite(pyglet.image.load("ChangedImage.png"))
        else:
            self.view.image = pyglet.sprite.Sprite(main.cache[main.curCacheIndex])
            self.view.image.scale = 1.0
        self.cur_scale = 1.0 # This is provisional for now, maybe we'll need it later


class STFViewControl(icuControl): #scale-to-fit view mode has the best acronym ever!

    def on_key_press(self, symbol, modifiers):
        if symbol == key.LEFT:
            self.mode.prevPic()
        elif symbol == key.RIGHT:
            self.mode.nextPic()
        elif symbol == key.UP:
            self.mode.dirUp()
        elif symbol == key.DOWN:
            self.mode.chooseDir()
        return False

    def on_mouse_press(self,x,y,button,modifiers):
        if button == mouse.RIGHT:
            self.mode.openPieMenu(x,y)
        return False

    def on_resize(self, width, height):
        self.mode.recalc = True
        self.mode.new_width = width
        self.mode.new_height = height
        return False


class STFViewView(icuView):  #currently does nothing. should interact with main to determine current picture to draw - that's it.
    
    def __init__(self, mode):
        self.closinganim = False
        self.mode = mode
        self.waitoneframe = False
        self.image = None
        self.oldimage = None

    def update(self,dt): pass

    def draw(self):
        self.image.draw()
        if self.waitoneframe: self.waitoneframe = False
        else:
            if self.oldimage is not None:
                self.oldimage.delete()
                self.oldimage = None
            if main.cache[2] is None:
                main.cache[2] = pyglet.image.load(main.piclist[(main.curIndex+1) % len(main.piclist)])
            elif main.cache[0] is None:
                main.cache[0] = pyglet.image.load(main.piclist[(main.curIndex-1) % len(main.piclist)])


class STFViewMode(icuMode):

    def __init__(self):
        self.control = STFViewControl(self)
        self.view = STFViewView(self)
        if len(main.piclist) == 0:
            self.view.image = pyglet.sprite.Sprite(pyglet.image.load("ChangedImage.png"))
        else:
            self.view.image = pyglet.sprite.Sprite(main.cache[main.curCacheIndex])

    def upperlayer(self): return False
            
    def nextPic(self):
        if len(main.piclist) > 0:
            main.curIndex = (main.curIndex + 1) % len(main.piclist)
            if len(main.piclist) > 3:
                # Have to shift the cache to the left
                main.cache[0] = main.cache[1]
                main.cache[1] = main.cache[2]
                
                main.cache[2] = None
                self.view.waitoneframe = True
                self.view.oldimage = self.view.image
#                main.cache[2] = pyglet.image.load(main.piclist[(main.curIndex+1) % len(main.piclist)])
                self.view.image = pyglet.sprite.Sprite(main.cache[1])
            else:
                # Small directory, don't need to adjust cache contents at all
                # Just change the cache index
                main.curCacheIndex = main.curCacheIndex+1 % len(main.cache)
                self.view.image = pyglet.sprite.Sprite(main.cache[main.curCacheIndex])
            #self.view.sprite.append(SpriteAnim(pyglet.sprite.Sprite(
            #	pyglet.image.load(main.piclist[main.curIndex]))))
    
    def prevPic(self):
        if len(main.piclist) > 0:
            main.curIndex = (main.curIndex - 1) % len(main.piclist)
            if len(main.piclist) > 3:
                # Have to shift the cache to the right
                main.cache[2] = main.cache[1]
                main.cache[1] = main.cache[0]
                main.cache[0] = None
                self.view.waitoneframe = True
                self.view.oldimage = self.view.image
#                main.cache[0] = pyglet.image.load(main.piclist[(main.curIndex-1) % len(main.piclist)])
                self.view.image = pyglet.sprite.Sprite(main.cache[1])
            else:
                # Small directory, don't need to adjust cache contents at all
                # Just change the cache index
                main.curCacheIndex = main.curCacheIndex-1 % len(main.cache)
                self.view.image = pyglet.sprite.Sprite(main.cache[main.curCacheIndex])
            #self.view.sprite.append(SpriteAnim(pyglet.sprite.Sprite(
            #	pyglet.image.load(main.piclist[main.curIndex]))))

    def draw(self):
        if self.recalc: self.recalcpos()
        self.view.draw()
        #if main.cache[2] is None:
        #    main.cache[2] = pyglet.image.load(main.piclist[(main.curIndex+1) % len(main.piclist)])
        #elif main.cache[0] is None:
        #    main.cache[0] = pyglet.image.load(main.piclist[(main.curIndex-1) % len(main.piclist)])

    def recalcpos(self):
        self.view.image.scale = 1.0
        self.view.image.scale = min(self.new_width/float(self.view.image.width),
                              self.new_height/float(self.view.image.height))
        self.view.image.x = (self.new_width - self.view.image.width)/2
        self.view.image.y = (self.new_height - self.view.image.height)/2

    def dirUp(self):
        main.loadDir(os.path.dirname(main.curdir))
        if len(main.piclist) == 0:
            self.view.image = pyglet.sprite.Sprite(pyglet.image.load("ChangedImage.png"))
        else:
            self.view.image = pyglet.sprite.Sprite(main.cache[main.curCacheIndex])

    def chooseDir(self):
        option = main.findFile()
        main.winman.window.activate()
        if option:
            main.loadDir(option)
            if len(main.piclist) == 0:
                self.view.image = pyglet.sprite.Sprite(pyglet.image.load("ChangedImage.png"))
            else:
                self.view.image = pyglet.sprite.Sprite(main.cache[main.curCacheIndex])
            

#def draw(self): self.view.sprite[0].draw(); main.winman.window.flip() #self.view.draw(); 
#control functions
    def openPieMenu(self,x,y):
            main.mode.append(ViewPieMode(x,y,ViewPieMode.SCALE_TO_FIT_MODE))


class ViewPieControl(icuControlUL):

    def on_mouse_press(self,x,y,button,modifiers):
        if button == mouse.LEFT:
            if not self.mode.hitEnter(x,y): self.mode.close()
        if button == mouse.RIGHT:
            self.mode.close()
        return False

    def on_mouse_drag(self,x,y,dx,dy,button,modifiers):
        if button == mouse.LEFT:
            self.mode.hitDrag(x,y,dx,dy)

    def on_mouse_release(self,x,y,button,modifiers):
        if button == mouse.LEFT:
            self.mode.hitExit(x,y)


class ViewPieMode(icuMode):

    SCALE_TO_FIT_MODE = 1
    ZOOM_MODE = 2
    PIXEL_MODE = 3
    SLIDESHOW_MODE = 4 #we may not have a right-click menu on slideshow mode, but might as well have the constant defined
    images = None

    def __init__(self,x,y,opener):
        self.closinganim = False
        self.view = icuView(self)
        self.control = ViewPieControl(self)
        w,h = main.winman.window.get_size()
        if self.__class__.images == None: #self.__class__.images is more formal, and I like to use it when caching images
            self.__class__.images = [pyglet.image.load("MenuEye-con.png"), #Scale-to-fit mode (yellow)
                                     pyglet.image.load("MenuEye-con.png"), #Zoom mode (orange)
                                     pyglet.image.load("MenuEye-con.png"), #Pixel mode (red)
                                     pyglet.image.load("MenuEye-con.png"), #Slideshow mode (purple)
                                     pyglet.image.load("MenuEye-con.png"), #Go up a folder (light teal)
                                     pyglet.image.load("MenuEye-con.png"), #Go into a folder (dark teal)
                                     pyglet.image.load("MenuEye-con.png"), #Refresh widget (light green)
                                     pyglet.image.load("MenuEye-con.png"), #Edit mode (green)
                                     pyglet.image.load("MenuEye-con.png"), #Zoom widget (dark blue)
                                     pyglet.image.load("SmallOrb.png")] #Zoom orbiter (light blue)
            for img in self.__class__.images: #center the anchor point (defaults to BL corner)
                img.anchor_x = img.width/2
                img.anchor_y = img.height/2

        angleamt = 360/8.
        if opener == self.SCALE_TO_FIT_MODE: #set up the center and three other view modes depending on current mode.
            centerspr = pyglet.sprite.Sprite(self.images[0],x,y)
            centerspr.opacity = 0
            centerspr.scale = 80/50.
            centerspr.color = (128,128,128)
            widroot = Widget(centerspr,25)#self.images[0],x,y),25)
            wid1 = widroot.attach(FuncWidget(pyglet.sprite.Sprite(self.images[1]),25,self.defaultfcn),0,0)
            wid2 = widroot.attach(FuncWidget(pyglet.sprite.Sprite(self.images[2]),25,self.defaultfcn),angleamt,0)
            wid3 = widroot.attach(FuncWidget(pyglet.sprite.Sprite(self.images[3]),25,self.defaultfcn),angleamt*2,0)

        wid1.sprite.opacity = 0; wid1.sanim.aalpha.offset = 0
        wid2.sprite.opacity = 0; wid2.sanim.aalpha.offset = 0
        wid3.sprite.opacity = 0; wid3.sanim.aalpha.offset = 0

        widroot.sanim.fadein([0.5]) #smoothly fade in center in half a second
        #move out from center in half a second fading in in 0.3s after 0.2s delay
        wid1.sanim.fadein([0.3],[],[0.2]); wid1.length.add([0.5],80,2)
        wid2.sanim.fadein([0.3],[],[0.2]); wid2.length.add([0.5],80,2)
        wid3.sanim.fadein([0.3],[],[0.2]); wid3.length.add([0.5],80,2)

        #force the full menu to be visible, regardless of right-clicked point, by smoothly moving the heirarchy into the screen
        pushamt = 105 #pixels
        widroot.sanim.ax.movto([0.5],max(pushamt,min(x,w-pushamt)),2)
        widroot.sanim.ay.movto([0.5],max(pushamt,min(y,h-pushamt)),2)

        for i in xrange(4,9):
            newsprite = pyglet.sprite.Sprite(self.images[i])
            newsprite.opacity = 0
            newwid = widroot.attach(FuncWidget(newsprite,25,self.defaultfcn),angleamt*(i-1),0)
            newwid.sanim.fadein([0.3],[],[0.2])
            newwid.length.add([0.5],80,2)#[0.2],80,2,[],[0.3])

        self.view.rootnode = widroot

    def hitEnter(self,x,y): return self.view.rootnode.hitenter(x,y)

    def hitExit(self,x,y): return self.view.rootnode.hitexit(x,y)

    def hitDrag(self,x,y,dx,dy):
        w,h = main.winman.window.get_size()
        pushamt = 105 #pixels
        if x < pushamt: dx = pushamt-self.view.rootnode.sprite.x
        elif x > w-pushamt: dx = w-pushamt-self.view.rootnode.sprite.x
        if y < pushamt: dy = pushamt-self.view.rootnode.sprite.y
        elif y > h-pushamt: dy = h-pushamt-self.view.rootnode.sprite.y
        return self.view.rootnode.hitdrag(x,y,dx,dy)

    def close(self):
        widroot = self.view.rootnode
        widroot.sanim.fadeout([0.3])
        for wid in widroot.child:
            wid.sanim.fadeout([0.3])
            wid.length.add([0.3],40,2)
        self.view.closinganim = True

    def defaultfcn(self,callingwidget):
        print "Clicked",callingwidget
        self.close()
        callingwidget.length.cut()
        callingwidget.length.add([0.3],-40,2)


if __name__ == "__main__":
    #main.mode.append(PixelZoomViewMode())
    main.mode.append(ZoomViewMode())
    #main.mode.append(STFViewMode())
    #pyglet.clock.schedule_interval(main.on_draw,1/60.0)
    pyglet.app.run()
